/**
 * 
 */
package com.magnusart.scrumify.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.magnusart.scrumppm.model.Project;
import com.magnusart.scrumppm.model.ProjectBuilder;
import com.magnusart.scrumppm.model.Story;
import com.magnusart.scrumppm.model.StoryBuilder;
import com.magnusart.scrumppm.model.Task;
import com.magnusart.scrumppm.model.TaskBuilder;

/**
 * @author Magnus Andersson
 *
 */
public class HsqlDbDAOFactory extends DAOFactory
{
	private static String driver = "jdbc:hsqldb:file:"+ System.getProperty( "user.dir" ) +"/db/live/yapes";
	private static String user = "sa";
	private static String password = "";
	
	private static Connection conn;
	
	
	/**
	 * Set a custom driver string for the JDBC connection
	 * @param driver The driver string eg "jdbc:hsqldb:file:/path/to/database" or "jdbc:hsqldb:mem:database". 
	 */
	final static void setDriver( String driver ) {
		HsqlDbDAOFactory.driver = driver;
	}



	/**
	 * Sets a custom database password
	 * @param password The password
	 */
	final static void setPassword( String password ) {
		HsqlDbDAOFactory.password = password;
	}



	/**
	 * Sets a custom database user
	 * @param user The user name.
	 */
	final static void setUser( String user ) {
		HsqlDbDAOFactory.user = user;
	}

	/**
	 * A seam that can be overridden in tests.
	 * @return A live Connection object.
	 */
	Connection getConnection() {
		// Make sure we have a driver to use.
		try {
			Class.forName("org.hsqldb.jdbcDriver" );
		} catch (Exception e) {
			System.err.println("Failed to load HSQLDB JDBC driver.");
			e.printStackTrace();
			return null;
		}
		
		try {
			if( !(conn instanceof Connection) )
				conn = DriverManager.getConnection( driver, user, password );
				
			return conn;	
		} catch ( SQLException sqle ) {
			System.err.println("Could not get a connection to the HSQLDB");
			return null;
		}
	}
	

	/**
	 * A seam that can be overridden in tests
	 * @param c Connection to close.
	 * @throws SQLException
	 */
	void closeConnection() throws SQLException {
		if( conn instanceof Connection ) {
			Statement st = conn.createStatement();
			// db writes out to files and performs clean shuts down
			// otherwise there will be an unclean shutdown
			// when program ends
			st.execute( "SHUTDOWN" );
			st.close();
		
			
			conn.close(); // if there are no other open connection.
			conn = null; // Let GC take care of the connection.
		}
	}

	/* (non-Javadoc)
	 * @see com.magnusart.yapes.dao.DAOFactory#getPDAO()
	 */
	@Override
	final public CommonDAO<Project, Project, ProjectBuilder> getProjectDAO() {
		return new HsqlDbProjectDAO( this );
	}
	
	final public ProjectDAO3 getProjectDAO3() {
		return new HsqlDbProjectDAO3( this );
	}
	
	/* (non-Javadoc)
	 * @see com.magnusart.yapes.dao.DAOFactory#getStoryDAO()
	 */
	@Override
	final public CommonDAO<Project, Story, StoryBuilder> getStoryDAO() {
		return new HsqlDbStoryDAO( this );
	}



	/* (non-Javadoc)
	 * @see com.magnusart.yapes.dao.DAOFactory#getTaskDAO()
	 */
	@Override
	final public CommonDAO<Story, Task, TaskBuilder>getTaskDAO() {
		return new HsqlDbTaskDAO( this );
	}



	final ResultSet executeQuery( String sql ) throws SQLException {
		ResultSet rs;
		Connection c = getConnection();
		
		// Execute the SQL Query and collect the ResultSet
		Statement st = c.createStatement();
		rs = st.executeQuery( sql );
		st.close();
		
		// Close the connection properly
		closeConnection();
		
		return rs;
	}
	
	final int executeUpdate( String sql ) throws SQLException {
		// Execute the SQL Query and collect the ResultSet
		Connection c = getConnection();
		Statement st = c.createStatement();
		int n = st.executeUpdate( sql );
		st.close();

		// Close the connection properly
		closeConnection();
		
		return n;
	}	
}
